home *** CD-ROM | disk | FTP | other *** search
/ Graphics Plus / Graphics Plus.iso / general / visulztn / saoimage / saoimage.lha / btnlib / image.c < prev    next >
C/C++ Source or Header  |  1991-08-03  |  12KB  |  336 lines

  1. #ifndef lint
  2. static char SccsId[] = "%W%  %G%";
  3. #endif
  4.  
  5. /*
  6.  * Module:    image.c (Make XImage)
  7.  * Project:    PROS -- ROSAT RSDC
  8.  * Purpose:    Stencil label icons onto blank (or prepared) button border
  9.  *        bitmaps and install as XImage's in the button record
  10.  * Subroutines:    btn_MakeXImages()        returns: void
  11.  * Subroutines:    static btn_AddLabel()        returns: void
  12.  * Subroutines:    static btn_LabelX()        returns: int
  13.  * Subroutines:    static btn_LabelY()        returns: int
  14.  * Xlib calls:    XCreateImage()
  15.  * Copyright:    1989 Smithsonian Astrophysical Observatory
  16.  *        You may do anything you like with this file except remove
  17.  *        this copyright.  The Smithsonian Astrophysical Observatory
  18.  *        makes no representations about the suitability of this
  19.  *        software for any purpose.  It is provided "as is" without
  20.  *        express or implied warranty.
  21.  * Modified:    {0} Michael VanHilst    initial version        18 March 1989
  22.  *        {n} <who> -- <does what> -- <when>
  23.  */
  24.  
  25. #include <stdio.h>        /* define NULL */
  26. #include <X11/Xlib.h>
  27. #include "buttons.h"
  28.  
  29. /*
  30.  * Subroutine:    btn_MakeXImages
  31.  * Purpose:    Create XImage bitmaps for four states of a button
  32.  * Returns:    void
  33.  * Called by:    btn_LabelButtons() in MakeBox.c
  34.  * Uses:    btn_Alloc() in BtnAlloc.c
  35.  * Uses:    btn_AddLabel() below;
  36.  * Xlib calls:    XCreateImage() with XYBitmap constant.
  37.  * Pre-state:    four model bitmaps with the border pattern installed
  38.  * Post-state:    off_out, off_in, on_out, on_in XImage's set in button record.
  39.  * Exception:    Only labels present are installed.
  40.  */
  41. void btn_MakeXImages ( button, width, height, byte_width, visual,
  42.                off_out, off_in, on_out, on_in, mapsz, off, on, motf )
  43.      ButtonRecord *button;    /* i: main structure describing button */
  44.      int width;            /* i: width in pixels of button */
  45.      int height;        /* i: height in pixels of button */
  46.      int byte_width;        /* i: width in bytes of the button bitmap */
  47.      Visual *visual;        /* i: visual for XCreateImage() */
  48.      unsigned char *off_out;    /* i: filled bitmap with only border pattern */
  49.      unsigned char *off_in;    /* i: filled bitmap with only border pattern */
  50.      unsigned char *on_out;    /* i: filled bitmap with only border pattern */
  51.      unsigned char *on_in;    /* i: filled bitmap with only border pattern */
  52.      int mapsz;            /* i: size of button bitmap in bytes */
  53.      int off, on;        /* i: reverse video when in on or off state */
  54.      int motf;            /* i: don't use occupied labels */
  55. {
  56.   unsigned char *data;        /* l: pointer to bitmap currently processing */
  57.   XImage *ximage;
  58.   char *btn_Alloc();
  59.   static void btn_AddLabel();
  60.  
  61. #ifdef ALLIANT
  62.   extern int nbutton;
  63. #endif
  64.  
  65.   /* put the dimensions in the button record */
  66.   button->width = (unsigned int)width;
  67.   button->height = (unsigned int)height;
  68.   /* make bitmap for unoccupied off state */
  69.   data = (unsigned char *)btn_Alloc(mapsz, sizeof(char), "button bitmap");
  70.   bcopy((char *)off_out, (char *)data, mapsz);
  71.   if( button->look->off_out_1 != NULL )
  72.     btn_AddLabel(button->look->off_out_1,
  73.          width, height, byte_width, data, off);
  74.   if( button->look->off_out_2 != NULL )
  75.     btn_AddLabel(button->look->off_out_2,
  76.          width, height, byte_width, data, off);
  77.   ximage = XCreateImage
  78.     (button->display, visual, (unsigned int)1, XYBitmap, 0, (char *)data,
  79.      (unsigned int)width, (unsigned int)height, 8, byte_width);
  80.   /* set for "bitmap" standard order */
  81.   ximage->byte_order = LSBFirst;
  82.   ximage->bitmap_bit_order = LSBFirst;
  83.   button->image[OFF_OUT] = ximage;
  84.   /* make bitmap for occupied off state */
  85.   data = (unsigned char *)btn_Alloc(mapsz, sizeof(char), "button bitmap");
  86.   bcopy((char *)off_in, (char *)data, mapsz);
  87.   if( motf ) {
  88.     if( button->look->off_out_1 != NULL )
  89.       btn_AddLabel(button->look->off_out_1,
  90.            width, height, byte_width, data, off);
  91.     if( button->look->off_out_2 != NULL )
  92.       btn_AddLabel(button->look->off_out_2,
  93.            width, height, byte_width, data, off);
  94.   } else {
  95.     if( button->look->off_in_1 != NULL )
  96.       btn_AddLabel(button->look->off_in_1,
  97.            width, height, byte_width, data, off);
  98.     if( button->look->off_in_2 != NULL )
  99.       btn_AddLabel(button->look->off_in_2,
  100.            width, height, byte_width, data, off);
  101.   }
  102.   ximage = XCreateImage
  103.     (button->display, visual, (unsigned int)1, XYBitmap, 0, (char *)data,
  104.      (unsigned int)width, (unsigned int)height, 8, byte_width);
  105.   /* set for "bitmap" standard order */
  106.   ximage->byte_order = LSBFirst;
  107.   ximage->bitmap_bit_order = LSBFirst;
  108.   button->image[OFF_IN] = ximage;
  109.   /* make bitmap for unoccupied on state */
  110.   data = (unsigned char *)btn_Alloc(mapsz, sizeof(char), "button bitmap");
  111.   bcopy((char *)on_out, (char *)data, mapsz);
  112.   if( motf > 1 ) {
  113.     if( button->look->on_in_1 != NULL )
  114.       btn_AddLabel(button->look->on_in_1, width, height, byte_width, data, on);
  115.     if( button->look->on_in_2 != NULL )
  116.       btn_AddLabel(button->look->on_in_2, width, height, byte_width, data, on);
  117.   } else {
  118.     if( button->look->on_out_1 != NULL )
  119.       btn_AddLabel(button->look->on_out_1,
  120.            width, height, byte_width, data, on);
  121.     if( button->look->on_out_2 != NULL )
  122.       btn_AddLabel(button->look->on_out_2,
  123.            width, height, byte_width, data, on);
  124.   }
  125.   ximage = XCreateImage
  126.     (button->display, visual, (unsigned int)1, XYBitmap, 0, (char *)data,
  127.      (unsigned int)width, (unsigned int)height, 8, byte_width);
  128.   /* set for "bitmap" standard order */
  129.   ximage->byte_order = LSBFirst;
  130.   ximage->bitmap_bit_order = LSBFirst;
  131.   button->image[ON_OUT] = ximage;
  132.   /* make bitmap for occupied on state */
  133.   data = (unsigned char *)btn_Alloc(mapsz, sizeof(char), "button bitmap");
  134.   bcopy((char *)on_in, (char *)data, mapsz);
  135.   if( motf == 1 ) {
  136.     if( button->look->on_out_1 != NULL )
  137.       btn_AddLabel(button->look->on_out_1,
  138.            width, height, byte_width, data, on);
  139.     if( button->look->on_out_2 != NULL )
  140.       btn_AddLabel(button->look->on_out_2,
  141.            width, height, byte_width, data, on);
  142.   } else {
  143.     if( button->look->on_in_1 != NULL )
  144.       btn_AddLabel(button->look->on_in_1, width, height, byte_width, data, on);
  145.     if( button->look->on_in_2 != NULL )
  146.       btn_AddLabel(button->look->on_in_2, width, height, byte_width, data, on);
  147.   }
  148.   ximage = XCreateImage
  149.     (button->display, visual, (unsigned int)1, XYBitmap, 0, (char *)data,
  150.      (unsigned int)width, (unsigned int)height, 8, byte_width);
  151.   /* set for "bitmap" standard order */
  152.   ximage->byte_order = LSBFirst;
  153.   ximage->bitmap_bit_order = LSBFirst;
  154.   button->image[ON_IN] = ximage;
  155. #ifdef ALLIANT
  156.   button->id[OFF_OUT] = nbutton++;
  157.   button->id[OFF_IN]  = nbutton++;
  158.   button->id[ON_OUT]  = nbutton++;
  159.   button->id[ON_IN]   = nbutton++;
  160. #endif
  161. }
  162.  
  163. /*
  164.  * Subroutine:    btn_AddLabel
  165.  * Purpose:    Add the label icon to a button's bitmap.
  166.  * Returns:    void
  167.  * Called by:    btn_CreateButtons()
  168.  * Uses:    btn_StencilLabel() in StencilLbl.c
  169.  * Uses:    btn_LabelX() or btn_LabelY() below
  170.  * Xlib calls:    none
  171.  * Pre-state:    bitmap already contains border pattern
  172.  * Post-state:    bitmap has label stenciled on
  173.  * Exception:    Label is not stenciled if one dimension would be zero.
  174.  * Method:    Get basic alignment parameters and call btn_StencilLabel();
  175.  */
  176. static void btn_AddLabel ( label, width, height, byte_width, bitmap, inverse )
  177.      ButtonLabel *label;    /* i: record of label bitmap to stencil in */
  178.      int width;            /* i: width in pixels of button */
  179.      int height;        /* i: height in pixels of button */
  180.      int byte_width;        /* i: width in bytes of the button bitmap */
  181.      unsigned char *bitmap;
  182.      int inverse;        /* i: invert the bits for reverse video look */
  183. {
  184.   int src_x, src_y;    /* l: coords of start of stencil in src (label) */
  185.   int dst_x, dst_y;    /* l: coords of start of stencil in dst (button) */
  186.   int xwdth;        /* l: width (cols) to stencil */
  187.   int yhght;        /* l: number of lines (rows) to stencil */
  188.   static int btn_LabelX(), btn_LabelY();
  189.   void btn_StencilLabel();
  190.  
  191.   if( ((xwdth = btn_LabelX(label, width, &src_x, &dst_x)) > 0) &&
  192.       ((yhght = btn_LabelY(label, height, &src_y, &dst_y)) > 0) ) {
  193.     btn_StencilLabel(label->label, label->mask, bitmap,
  194.              label->bytes_per_line, byte_width, src_x, src_y,
  195.              dst_x, dst_y, xwdth, yhght, inverse);
  196.   }
  197. }
  198.  
  199. /*
  200.  * Subroutine:    btn_LabelX
  201.  * Purpose:    Determine width and x coordinates to copy label onto the button
  202.  * Returns:    width to copy
  203.  * Called by:    btn_AddLabel() above
  204.  * Uses:    nothing
  205.  * Xlib calls:    none
  206.  * Pre-state:    label structure with 
  207.  * Post-state:    dst bitmap has label stenciled on
  208.  * Method:    If there is enough room, the entire label is copied.  If not,
  209.  *        the x_clip value indicates what to cut off.  If x_clip=0, the
  210.  *        same amount is removed from both sides.  If x_clip!=0, use
  211.  *        the breaks array to select a specific break point (usually
  212.  *        representing the breaks between characters).  If x_clip>0
  213.  *        cut from the left, if x_clip<0 cut from the left.
  214.  *        The postition within the button is determined by x_ratio:
  215.  *        0 is at the left, .5 in the middle, 1 at the right, and then
  216.  *        offset x_offset pixels.  This has no meaning when cutting was
  217.  *        needed, as the label will fill the entire width.
  218.  */
  219. static int btn_LabelX ( label, width, lbl_x, btn_x )
  220.      ButtonLabel *label;
  221.      int width;
  222.      int *lbl_x;
  223.      int *btn_x;
  224. {
  225.   int xwdth;
  226.  
  227.   /* if full label height fits */
  228.   if( width >= label->width ) {
  229.     *lbl_x = 0;
  230.     xwdth = label->width;
  231.   /* else label must be clipped to fit */
  232.   } else {
  233.     /* clip symmetrically on both ends, use button's width */
  234.     if( label->x_clip == 0 ) {
  235.       *lbl_x = (label->width - width) / 2;
  236.       *btn_x = 0;
  237.       return( width );
  238.     /* clip at given quanta */
  239.     } else {
  240.       /* find the appropriate length */
  241.       int stop;
  242.  
  243.       stop = label->x_clip;
  244.       if( stop < 0 )
  245.     stop = -stop;
  246.       while( ((--stop) >= 0) && (label->breaks[stop] > width) );
  247.       if( stop < 0 )
  248.     return( 0 );
  249.       else
  250.     xwdth = label->breaks[stop];
  251.       /* set the appropriate starting offset */
  252.       if( label->x_clip > 0 )
  253.     *lbl_x = 0;
  254.       else
  255.     *lbl_x = label->width - xwdth;
  256.     }
  257.   }
  258.   /* determine where to start in button (first ideal, then adjest if needed) */
  259.   *btn_x = ((width - xwdth) * label->x_ratio) + label->x_offset;
  260.   if( *btn_x < 0 ) {
  261.     *btn_x = 0;
  262.   } else if( *btn_x > (width - xwdth) ) {
  263.     *btn_x = width - xwdth;
  264.   }
  265.   return( xwdth );
  266. }
  267.  
  268. /*
  269.  * Subroutine:    btn_LabelY
  270.  * Purpose:    Determine height and y coordinates to copy label onto button
  271.  * Returns:    height to copy
  272.  * Called by:    btn_AddLabal() above
  273.  * Uses:    nothing
  274.  * Xlib calls:    none
  275.  * Pre-state:    label structure with 
  276.  * Post-state:    dst bitmap has label stenciled on
  277.  * Method:    If there is enough room, the entire label is copied.  If not,
  278.  *        the y_clip value indicates what to cut off.  If y_clip=0, the
  279.  *        same amount is removed from both sides.  If y_clip!=0, use
  280.  *        the breaks array to select a specific break point (usually
  281.  *        representing the breaks between characters).  If y_clip>0
  282.  *        cut from the left, if y_clip<0 cut from the left.
  283.  *        The postition within the button is determined by y_ratio:
  284.  *        0 is at the left, .5 in the middle, 1 at the right, and then
  285.  *        offset y_offset pixels.  This has no meaning when cutting was
  286.  *        needed, as the label will fill the entire height.
  287.  */
  288. static int btn_LabelY ( label, height, lbl_y, btn_y )
  289.      ButtonLabel *label;
  290.      int height;
  291.      int *lbl_y;
  292.      int *btn_y;
  293. {
  294.   int yhght;
  295.  
  296.   /* if full label height fits */
  297.   if( height >= label->height ) {
  298.     *lbl_y = 0;
  299.     yhght = label->height;
  300.   /* else label must be clipped to fit */
  301.   } else {
  302.     /* clip symmetrically on both ends, use button's height */
  303.     if( label->y_clip == 0 ) {
  304.       *lbl_y = (label->height - height) / 2;
  305.       *btn_y = 0;
  306.       return( height );
  307.     /* clip at given quanta */
  308.     } else {
  309.       /* find the appropriate length */
  310.       int stop;
  311.  
  312.       stop = label->y_clip;
  313.       if( stop < 0 )
  314.     stop = -stop;
  315.       while( ((--stop) >= 0) && (label->breaks[stop] > height) );
  316.       if( stop < 0 )
  317.     return( 0 );
  318.       else
  319.     yhght = label->breaks[stop];
  320.       /* set the appropriate starting offset */
  321.       if( label->y_clip > 0 )
  322.     *lbl_y = 0;
  323.       else
  324.     *lbl_y = label->height - yhght;
  325.     }
  326.   }
  327.   /* determine where to start in button (first ideal, then adjest if needed) */
  328.   *btn_y = ((height - yhght) * label->y_ratio) + label->y_offset;
  329.   if( *btn_y < 0 ) {
  330.     *btn_y = 0;
  331.   } else if( *btn_y > (height - yhght) ) {
  332.     *btn_y = height - yhght;
  333.   }
  334.   return( yhght );
  335. }
  336.